<!DOCTYPE html>
<html>
  <head>
    <title>推箱子地图编辑</title>
    <meta charset="utf-8">
  </head>
  <body>
	<script type="text/javascript" src="../libs/minicomps.min.js"></script>
	<script type="text/javascript" src="../libs/FileSaver.js"></script>
	<script type="text/javascript" src="../libs/easeljs.js"></script>
	<script type="text/javascript" src="../libs/Unify.js"></script>
	<script>
	//推箱子https://www.4399.com/flash/25819_3.htm
	//通关视频 https://www.bilibili.com/video/BV1hh41147Pu/?spm_id_from=autoNext&vd_source=8713e6720ca2ecae7f1110a44f5de6a
	const { Toggle, HSlider,VSlider,Panel, Canvas ,Button,TextArea,TextBox,TextInput,Label,Window,LabelInput,TipsManager,RadioButton,ColorPicker,TabbarWindow,Checkbox,Knob,Stage,MoonTextArea,Dropdown,TabbarButton,ProgressBar} = mc
	const width = Stage.width;
	const height = Stage.height;
	const panel = new Panel(document.body, 0, 0, 10,10);
	const Const={UP:'上',DOWN:'下',LEFT:'左',RIGHT:'右',STOP:'停'};
	const ConstKey={W:'w',S:'s',A:'a',D:'d'};
	const NUM=10;
	const WID=40;
	const objects = ['wall','target','box','player'];
	var tip='推箱子：1围墙， 2目标点， 3箱子， 4角色， 5在目标点的箱子';
	tip+='\n注意事项：围墙必须是闭合的，目标点和箱子数量必须一样多，必须也只能有一个角色'
	tip+='\n小车编程：0空地， 1城墙， 2障碍物， 3障碍物， 4小车， 5目标地，6为星星，7静止敌方，8四周开炮敌人，9左右移动敌人，10上下移动敌人'
	var createStage;
	var group=1;
	var saveKey='tuixiangziGame';
	var copyData={};
	function updateColor(t){
		//console.log(t.toRGBString(),t.toString());
		if(currPanel&&currPanel.updateColor){
			currPanel.updateColor(t);
		}
	}
	var colors=['rgba(255,255,0,0.1)','#FF0000','#00bb00','#11dddd','#BB3300','#666600','#660000','#333399','#006666','#006633','#003300','#0033ff'];
	const g={
			wall:{color:'#333',data:[],boxs:[]},
			target:{color:'#9f3',data:[],boxs:[]},
			box:{color:'rgba(255,50,0,0.8)',data:[],boxs:[]},
			player:{color:'rgba(255,220,0,0.8)',data:[],boxs:[]}
		}		
	/**键盘事件*/
	window.keyDownData={};
	window.keyUpData={};
	window.addEventListener('keydown', keyDownCb,true);
	window.addEventListener('keyup', keyUpCb,true);
	function keyDownCb(e){
		//console.log(e.keyCode);
		for( var i in window.keyDownData){
			window.keyDownData[i](e);
		}
	}
	function keyUpCb(e){
		for( var i in window.keyUpData){
			window.keyUpData[i](e);
		}
	}
	/**数字格式，把小于10的数在前面加个0*/
	function numberFormat(num){
		if(num>=10)			return String(num);
		else				return "0"+num;
	}
	/**复制字符串*/
	function copyString(input){
		input.select();
		document.execCommand('Copy');
		TipsManager.alert('复制成功');
	}
	/**复制字符串*/
	function copyString2(text) {
		// text是复制文本
		// 创建input元素
		const el = document.createElement('input')
		// 给input元素赋值需要复制的文本
		el.setAttribute('value', text)
		// 将input元素插入页面
		document.body.appendChild(el)
		// 选中input元素的文本
		el.select()
		// 复制内容到剪贴板
		document.execCommand('copy')
		// 删除input元素
		document.body.removeChild(el)
		TipsManager.alert('复制成功');
	}
	//基础面板
	class BasicPanel {
		constructor(label){
			this.isShow=true;
            this.p=new Canvas(document.body, 0, 0,width-10,height-15);
			this.p.setColorDark();
			new Label(this.p,5,-15,label).setBold(true).setFontSize(15);
		}
		set visible(value){//复盖父级方法
			if(this.isShow!=value){
				if(value) this.p.addFromParent();
				else	  this.p.removeFromParent();
			}
			this.isShow=value;
		}
		initData(){//子类去实现

		}
		setData(data){//子类去实现

		}
		setDataWindow(){
			this.dataWindow=new Window(this.p,0,0,window.innerWidth-150,window.innerHeight-100);
			this.dataWindow.visible=false;
			this.dataText=new MoonTextArea(this.dataWindow,0,22).setSize(this.dataWindow.width,this.dataWindow.height);
			this.dataWindow.btnClose=new Button(this.dataWindow,0,0,'复制关闭窗口',(e)=>{
				copyString(this.dataText.input);
				this.dataWindow.visible=false;
			});
			this.dataWindow.setContent=(str)=>{
				this.dataWindow.visible=true;
				this.dataText.text=str;
			}
		}
	}
	//-----------------地图编辑大师-----------------
	class MapToolPanel extends BasicPanel{
		constructor(label){
			super(label);
			this.propBtns=[];
			this.initView();
			this.initEvent();

			this.createMap({detail:true});//测试
		}
		initView(){
			this.canvas=new Canvas(this.p, 150, 0,width-260,height-30);
			this.realityCanvas=this.canvas.realityCanvas;
			var [x,y]=[5,-10];
			this.xTxt=new LabelInput(this.p,5,y+=22,'x轴数量').input;
			this.xTxt.setSize(50).text=NUM;
			this.yTxt=new LabelInput(this.p,5,y+=22,'y轴数量').input;
			this.yTxt.setSize(50).text=NUM;
			this.wMap=new LabelInput(this.p,5,y+=22,'小地图宽').input;
			this.wMap.setSize(50).text=WID;
			new Button(this.p,x,y+=22,'创建地图',(e)=>{TipsManager.SureCancel(`确定创建${this.xTxt.text}x${this.yTxt.text}的地图吗？`,this.createMap.bind(this))});
			
			this.txtLevel=new Label(this.p,10,y+=25,'当前无关卡');
			
			this.colors=['rgba(255,255,0,0.1)','#FF0000','#00cc00','#0000ff','#BBBB00','#666600','#660000','#333399','#006666','#006633','#003300','#0033ff'];
			this.status=1;
			var [x,y,g,radios]=[5,110,++group,[]];
			this.inputs=[];
			let arr=['清除数据','使用数据1','使用数据2','使用数据3','使用数据4','使用数据5','使用数据6','使用数据7','使用数据8','使用数据9','使用数据10'];
			for(let i=0;i<arr.length;i++){
				radios.push(new RadioButton(this.p, x, (y+=22)+4, g, arr[i], i==1, (e)=>{
					this.status=radios.indexOf(e.target);
				}));
				this.inputs.push(new TextInput(this.p,x+80,y,i,this.onInput.bind(this)).setSize(30));
			}
			new Button(this.p,x,y+=22,'生成数据',this.openCreateData.bind(this));
			new Button(this.p,x,y+=22,'试玩游戏',this.startGame.bind(this));
			new Button(this.p,x,y+=22,'重置游戏',this.restartGame.bind(this));
			new Button(this.p,x,y+=22,'保存本地数据',this.saveData.bind(this));
			new Button(this.p,x,y+=22,'读取本地数据',this.readData.bind(this));
			new Button(this.p,x,y+=22,'删除本地数据',(e)=>{TipsManager.SureCancel(`请在下方输入确认删除`,this.deleteData.bind(this),true)});
			new Button(this.p,x,y+=22,'读取外部数据',(e)=>{TipsManager.SureCancel(`把数据输入到下方(单条/多条)`,this.parseData.bind(this),true)});
			
			this.setDataWindow();

			window.keyDownData['MapToolPanel']=(e)=>{
				this.updateKeyDown(e.keyCode);
			}
			let smPanel=new Panel(this.p,0,height-60,width,60);
			(new TextArea(smPanel,0,0,tip)).setSize(width);

			this.menu=new Window(null,40,40,width-100,height-100,'关卡菜单');
		}
		onInput(e){
			let i=this.inputs.indexOf(e.target);
			let text=e.detail;
			this.maps.forEach((a)=>{
				if(a.data.id==i){
					a.data.text=text;
					a.update();
				}
			})
			this.stage.update();
		}
		initEvent(){
			this.stage=new createjs.Stage(this.realityCanvas);
			this.stage.addEventListener("stagemousedown", this.handleMouseDown.bind(this));
			this.stage.addEventListener("stagemousemove", this.handleMouseMove.bind(this));
			this.stage.addEventListener("stagemouseup", this.handleMouseUp.bind(this));
			this.createBg('#ffffff');
			this.mapLayer=new createjs.Container();
			this.stage.addChild(this.mapLayer);
		}
		handleMouseDown(event) {
			this.isDown=true;
			this.drawData={color:this.colors[this.status],text:this.inputs[this.status].text,id:this.status};
			const { x, y } = this.getPos(event);
			this.handleMouseMove(event);
		}
		handleMouseMove(event) {
			if(this.isPlay)return;
			if(this.isDown){
				const { x, y } = this.getPos(event);
				let len=this.maps.length;
				for(var i=0;i<len;i++){
					let a=this.maps[i];
					if(a.hitTest(x, y)){
						a.setData(this.drawData);
						this.stage.update();
						break;
					}
				}
			}
		}
		handleMouseUp(event) {
			this.isDown=false;
			this.stage.update();
		}
		/**解析数据*/
		parseData(e){
			if(e.detail){
				let value=e.value;
				if(value){
					let len=value.length;
					if(len<300){//单条数据
						this.level=JSON.parse(value);
						this.restartGame();
					}else{//多条数据
						try{
							let datas=JSON.parse(value);
							localStorage.setItem(this.saveKey,JSON.stringify(datas));
							TipsManager.alert('多条数据读取成功，请点击 《读取本地数据》 选择关卡');
						}catch(e){
							TipsManager.alert('原始数据有错误');
							return;
						}
					}
				}
			}
			this.dataIndex=-1;
		}
		/**重置游戏*/
		restartGame(){
			this.isPlay=false;
			let level=this.level;
			this.mapLayer.removeAllChildren();
			const [ x, y ,w] = [NUM,NUM,WID];
			this.maps=[];
			this.mapDatas=[];
			for(let i=0;i<y;i++){
				this.mapDatas.push([]);
				for(let j=0;j<x;j++){
					let map=new MapItem(w,w);
					map.pos=[j,i];
					this.mapLayer.addChild(map);
					this.maps.push(map);
					this.mapDatas[i].push(map);
					let id=level[i][j];
					let da={color:this.colors[id],text:this.inputs[id].text,id:id};
					map.setData(da);
				}
			}
			Unify.displayRank(this.maps,x);
			this.stage.update();
		}
		/**开始试玩*/
		startGame(){
			if(this.mapDatas){
				this.isPlay=true;
				let level=this.createData();
				this.level=level;
				//console.log(level);
				var num=NUM;
				objects.forEach(a=>{
					g[a].data.length=0
					g[a].boxs.length=0
				});
				for(let i=0;i<num;i++){
					for(let j=0;j<num;j++){
						let d=level[i][j];
						let id = i*num+j;
						let [x,y] = [id%NUM,~~(id/NUM)];
						let map=this.mapDatas[y][x]
						if(d>0){
							if(d==5){
								//console.log('dddddd',d)
								g['target'].data.push(id);
								g['box'].data.push(id);
								let da=map.data;
								da.id=2;da.color=this.colors[2];da.text=2
								map.setData(da);
								let boxMap=new MapItem(WID,WID);
								[boxMap.x,boxMap.y]=[map.x,map.y];
								this.mapLayer.addChild(boxMap);
								let boxDa={color:this.colors[3],text:this.inputs[3].text,id:3,pos:map.pos};
								boxMap.setData(boxDa)
								g['target'].boxs.push(map);
								g['box'].boxs.push(boxMap);
							}else{
								g[objects[d-1]].data.push(id);
								g[objects[d-1]].boxs.push(map);
							}
						}
					}
				}
				g['player'].boxs.forEach(a=>a.setBestHeight());
        		g['box'].boxs.forEach(a=>a.setBestHeight());
				this.stage.update();
				//console.log(g);
			}
		}
		updateKeyDown(key){
			//方向键,根据方向键，dir移动的id
			if(!this.isPlay){
				TipsManager.alert('请切换到试玩模式');
				return;
			}
			let dir = [-1,-NUM,1,NUM][key-37];
			if(!dir)return;
			let playerid = g.player.data[0];
			let next = playerid+dir;
			//判断是否撞墙	
			if(g.wall.data.includes(next)) return;
			//判断是否移动箱子	 
			if(g.box.data.includes(next)){
				let boxid=next;
				let boxnext = boxid+dir;
				//判断箱子是否撞墙或撞箱子
				if(g.wall.data.includes(boxnext)||g.box.data.includes(boxnext)) return;
				this.move('box',boxid,dir);
			}
			//移动玩家角色
			this.move('player',playerid,dir);
			//判断游戏结束
			this.checkOver();
		}
		//移动玩家角色和箱子
		move(who,id,dir){
			let next = id+dir;
			let index = g[who].data.indexOf(id);
			g[who].data[index]=next;
			let map=g[who].boxs[index];
			let [x,y]=[next%NUM*WID,~~(next/NUM)*WID];
			//console.log(x,y);
			[map.x,map.y]=[x,y]
			this.stage.update();
		}
		//判断游戏结束
		checkOver(){
			let win = g.box.data.every(b=>g.target.data.includes(b));
			if(win){
					setTimeout(()=>{
					alert("恭喜过关！")	
				},100)
			}
		}
		getPos(evt) {
			return {
				x: evt.stageX,
				y: evt.stageY
			}
		}
		createMap(e){
			if(e.detail){
				this.dataIndex=-1;
				this.mapLayer.removeAllChildren();
				const [ x, y ,w] = [Number(this.xTxt.text),Number(this.yTxt.text),Number(this.wMap.text)];
				this.maps=[];
				this.mapDatas=[];
				for(let i=0;i<y;i++){
					this.mapDatas.push([]);
					for(let j=0;j<x;j++){
						let map=new MapItem(w,w);
						map.pos=[j,i];
						this.mapLayer.addChild(map);
						this.maps.push(map);
						this.mapDatas[i].push(map);
					}
				}
				Unify.displayRank(this.maps,x);
				this.stage.update();
				this.minMapWid=w;
			}			
		}
		openCreateData(){
			this.createData();
			let value=this.arrStr;
			this.dataWindow.setContent(value);
			console.log(this.arrStr);
		}
		createData(){
			if(!this.mapDatas)return;
			var arr=[];
			var arrStr='[';
			const [ x, y] =[this.mapDatas.length,this.mapDatas[0].length]; 
			for(let i=0;i<x;i++){
				let maps=this.mapDatas[i];
				arr.push([]);
				arrStr+='['
				for(let j=0;j<y;j++){
					let m=maps[j];
					arr[i].push(m.data.id);
					if(j<y-1)	arrStr+=m.data.id+',';
					else		arrStr+=m.data.id;
				}
				if(i<x-1)	arrStr+='],'
				else		arrStr+=']'
			}
			arrStr+=']';
			this.arrStr=arrStr;
			return arr;
		}
		saveData(e){
			let datas=localStorage.getItem(this.saveKey)||[];
			if(!Array.isArray(datas)){
				try{
					datas=JSON.parse(datas);
				}catch(e){
					TipsManager.alert('原始数据有错误');
					return;
				}
			}
			var arr=this.createData();
			if(this.dataIndex>=0){
				datas[this.dataIndex]=arr;
			}else{
				datas.push(arr);
			}
			//console.log(datas);
			TipsManager.alert('保存成功');
			localStorage.setItem(this.saveKey,JSON.stringify(datas));
		}
		readData(e){
			let datas=localStorage.getItem(this.saveKey);
			if(datas){
				try{
					datas=JSON.parse(datas);
				}catch(e){
					TipsManager.alert('原始数据有错误');
					return;
				}
				//console.log(datas);
			}else{
				datas=[];
			}
			this.p.addChild(this.menu);
			this.menu.removeAllChildren();
			new Button(this.menu,10,0,'关闭',(e)=>{this.p.removeChild(this.menu);}).setSize(80);
			let [xNum,x,y]=[10,10,25];
			for(let i=0;i<datas.length;i++){
				let btn=new Button(this.menu,0,0,'关卡：'+i,this.onBtnClick.bind(this));
				btn.data=datas[i];
				btn.setSize(80,25);
				btn.dataIndex=i;
				btn.x=x+parseInt(i%xNum)*(btn.width+2);
				btn.y=y+parseInt(i/xNum)*(btn.height+2);

				// var show=JSON.stringify(btn.data);
				// if(i<datas.length-1) show+=','
				// console.log(show);
			}
			console.log(JSON.stringify(datas));
		}
		onBtnClick(e){
			//console.log(e.target.data);
			this.dataIndex=e.target.dataIndex;
			this.level=e.target.data;
			this.restartGame();
			this.p.removeChild(this.menu);

			this.txtLevel.text='当前第'+this.dataIndex+'关'
		}
		deleteData(e){
			if(e.detail){
				if(e.value=='确认删除'){
					localStorage.removeItem(this.saveKey);
					TipsManager.alert('删除成功');
				}
			}
			this.dataIndex=-1;
		}
		createBg(color){
			if(!this.bg){
				this.bg=new createjs.Shape();
				this.bg.graphics.beginFill(color).drawRect(0,0,this.canvas.width,this.canvas.height);
				this.stage.addChildAt(this.bg,0);
			}else{
				this.bg.graphics.clear().beginFill(color).drawRect(0,0,this.canvas.width,this.canvas.height);
			}
			this.stage.update();
		}
	}
	class MapItem extends createjs.Container{
		constructor(w,h){
			super();
			this.data={id:0};
			this.width=w;
			this.height=h;
			this.shape=new createjs.Shape();
			this.colorBg="rgba(255,255,0,0.1)";
			this.colorMap="rgba(255,0,0,1)";
			this.drawBox(this.colorBg);
			this.addChild(this.shape);
			this.label=new createjs.Text('',"15px Arial", "#ffffff");
			this.label.x=3;
			this.label.y=3;
			this.label.textAlign='left';
			this.addChild(this.label);
		}
		drawBox(color){
			let[w,h]=[this.width,this.height];
			this.shape.graphics.clear();
			this.shape.graphics.setStrokeStyle(1);
			this.shape.graphics.beginStroke("black");
			this.shape.graphics.beginFill(color).drawRect(0,0,w,h);
		}
		hitTest(x,y){
			if(x>=this.x&&x<=this.x+this.width){
				if(y>=this.y&&y<=this.y+this.height){
					return true;
				}
			}
			return false;
		}
		setData(data){
			this.data.id=data.id;
			this.data.text=data.text;
			this.data.color=data.color;
			this.data.event=data.event;
			this.data.param=data.param;
			this.data.config=data.config;
			this.data.pos=data.pos;
			this.update();
		}
		setNewId(data){
			this.data.id=data.id;
			this.data.text=data.id;
			this.data.color=colors[data.id];
			this.data.event=data.event;
			this.data.config=data.config;
			this.data.pos=data.pos;
			this.update();
		}
		setBestHeight(){
			let index=this.parent.children.length-1;
			this.parent.setChildIndex(this,index)
		}
		update(){
			this.label.text=this.data.text||'';
			this.drawBox(this.data.color);
			//console.log(this.label.text,this.data.color);
		}
	}
	//--所有面板----
	var btnNames=['地图编辑'];
	var buttons=[];
	var currPanelIndex=0;
	var currPanel=null;
	for(var i=0;i<btnNames.length;i++){
		var btn=new Button(panel,2,2+22*i,btnNames[i],onClick);
		buttons.push(btn);
		btn.setSize(88);
		btn.name=i;
	}
	
	function onClick(e){
		let btn=e.target;
		changeView(btn);
	}
	function changeView(btn){
		let name=btn.name;
		buttons.forEach((b)=>{b.enabled=true;});
		btn.enabled=false;
		for(var i=0;i<panels.length;i++){
			panels[i].visible=false;
		}
		currPanel=panels[name];
		currPanel.visible=true;
		currPanel.initData();
		currPanelIndex=name;
		
	}
	var panelClass=[
		[MapToolPanel,'地图编辑大师']
	];
	var panels=[];
	for(var i=0;i<panelClass.length;i++){
		let panel=new panelClass[i][0](panelClass[i][1]);
		panel.visible=false;
		panels.push(panel);
	}
	changeView(buttons[0]);
	</script>
  </body>
</html>